﻿/*
* Copyright 2009-2010 AKABANA.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
using System;
using System.IO;
using System.Text;
using Akabana.Amf.Serializer;

namespace Akabana.Amf.IO
{
    public class AmfReader : BinaryReader
    {
        private IAmfDeserializer _amfDeserializer;

        public ushort version { get; set; }

        public AmfReader(Stream input)
            : base(input, Encoding.UTF8)
        {
            this.version = ReadVersion();
            _amfDeserializer = AmfSerializerFactory.CreateDeserializer(version, this);
        }

        public AmfReader(Stream input, ushort version)
            : base(input, Encoding.UTF8)
        {
            this.version = version;
            _amfDeserializer = AmfSerializerFactory.CreateDeserializer(version,this);
        }

        public ushort ReadVersion()
        {
            return this.ReadU16();
        }

        public ushort ReadU16()
        {
            var byte1 = ReadByte();
            var byte2 = ReadByte();
            if ((byte1 | byte2) < 0)
            {
                throw new EndOfStreamException();
            }
            return (ushort)(((byte1 << 8) | byte2) & 0xFFFF);
        }

        public short ReadS16()
        {
            var byte1 = ReadByte();
            var byte2 = ReadByte();
            if ((byte1 | byte2) < 0)
            {
                throw new EndOfStreamException();
            }
            return (short)(((byte1 << 8) | byte2) & 0xFFFF);
        }

        public uint ReadU32()
        {
            var byte1 = ReadByte();
            var byte2 = ReadByte();
            var byte3 = ReadByte();
            var byte4 = ReadByte();
            if ((byte1 | byte2 | byte3 | byte4) < 0)
            {
                throw new EndOfStreamException();
            }
            return (uint)((byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4);
        }

        public string ReadUtfString()
        {
            var targetSize = ReadU16();
            var stringData = new byte[targetSize];
            Read(stringData, 0, targetSize);
            return Encoding.UTF8.GetString(stringData, 0, targetSize);
        }

        public double ReadNumber()
        {
            var byteArray = ReadBytes(sizeof(double));

            for (int i = 0; i < 4; i++)
            {
                var temp = byteArray[i];
                byteArray[i] = byteArray[7 - i];
                byteArray[7 - i] = temp;
            }
            return BitConverter.ToDouble(byteArray, 0);
        }

        public object ReadObject()
        {
            return _amfDeserializer.Deserialize();
        }
    }
}
